package com.imooc.controller;

import com.imooc.pojo.Users;
import com.imooc.pojo.bo.ShopCartBO;
import com.imooc.pojo.bo.UserBO;
import com.imooc.pojo.vo.UserVO;
import com.imooc.service.UserService;
import com.imooc.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: foodie-dev
 * @description: 登陆控制层
 * @author: rZ
 * @create: 2020-03-07 11:14
 **/
@Api(value = "注册登陆", tags = {"用于注册登陆的相关接口"})
@RestController
@RequestMapping("passport")
public class PassportController extends BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisOperator redisOperator;

    /**
     * 注册确认用户名是否存在
     *
     * @param username
     * @return
     */
    @ApiOperation(value = "用户名是否存在", notes = "用户名是否存在", httpMethod = "GET")
    @GetMapping("/usernameIsExist")
    public IMOOCJSONResult usernameIsExist(@RequestParam String username) {
        //入参不能为空
        if (StringUtils.isBlank(username)) {
            return IMOOCJSONResult.errorMsg("用户名不能为空");
        }
        //查找注册的用户名是否存在
        boolean isExit = userService.queryQueryUsernameIsExist(username);
        if (isExit) {
            return IMOOCJSONResult.errorMsg("用户名已经存在");
        }
        //请求成功
        return IMOOCJSONResult.ok();
    }

    /**
     * 用户注册的方法
     *
     * @param userBO
     * @return
     */
    @ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
    @PostMapping("regist")
    public IMOOCJSONResult regist(@RequestBody UserBO userBO,
                                  HttpServletRequest request,
                                  HttpServletResponse response) {

        String username = userBO.getUsername();
        String password = userBO.getPassword();
        String confirmPassword = userBO.getConfirmPassword();

        //0.判断用户名和密码必须不为空
        if (StringUtils.isBlank(username) ||
                StringUtils.isBlank(password) ||
                StringUtils.isBlank(confirmPassword)) {
            return IMOOCJSONResult.errorMsg("用户名或密码不能为空");
        }
        //1.查询用户名是否存在
        boolean isExit = userService.queryQueryUsernameIsExist(username);
        if (isExit) {
            return IMOOCJSONResult.errorMsg("用户名已经存在");
        }
        //2.密码长度不能少于6位
        if (password.length() < 6) {
            return IMOOCJSONResult.errorMsg("密码长度不能小于6");
        }
        //3.判断两次密码是否一致
        if (!password.equals(confirmPassword)) {
            return IMOOCJSONResult.errorMsg("两次密码输入不一致");
        }
        //4.实现注册
        Users userResult = userService.createUser(userBO);

        //userResult = setNullProperty(userResult);

        //实现用户的redis会话
        UserVO userVO = convertUserVO(userResult);

        CookieUtils.setCookie(request, response, "user",
                JsonUtils.objectToJson(userVO), true);

        //同步购物车数据
        synchShopCartData(userResult.getId(), request, response);
        return IMOOCJSONResult.ok();
    }

    /**
     * 用户登录的方法
     *
     * @param userBO
     * @return
     */
    @ApiOperation(value = "用户登陆", notes = "用户登陆", httpMethod = "POST")
    @PostMapping("login")
    public IMOOCJSONResult login(@RequestBody UserBO userBO,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws Exception {

        String username = userBO.getUsername();
        String password = userBO.getPassword();

        //0.判断用户名和密码必须不为空
        if (StringUtils.isBlank(username) ||
                StringUtils.isBlank(password)) {
            return IMOOCJSONResult.errorMsg("用户名或密码不能为空");
        }

        //1.实现登陆
        Users userResult = userService.queryUserForLogin(username,
                MD5Utils.getMD5Str(password));
        if (userResult == null) {
            return IMOOCJSONResult.errorMsg("用户名或密码不正确");
        }

        //userResult = setNullProperty(userResult);

        //实现用户的redis会话
        UserVO userVO = convertUserVO(userResult);

        CookieUtils.setCookie(request, response, "user",
                JsonUtils.objectToJson(userVO), true);

        //同步购物车数据
        synchShopCartData(userResult.getId(), request, response);

        return IMOOCJSONResult.ok(userResult);
    }

    /**
     * 注册登录成功后，同步cookie和redis中的购物车数据
     */
    private void synchShopCartData(String userId, HttpServletRequest request,
                                   HttpServletResponse response) {

        /**
         * 1.redis中无数据，如果cookie中的购物车为空，那么这个时候不做任何处理
         *                如果cookie中的购物车不为空，此时直接放入redis中
         * 2.redis中有数据，如果cookie中的购物车为空，那么直接把redis的购物车覆盖本地cookie
         *                如果cookie中的购物车不为空，如果cookie中的某个商品在redis中存在，则以cookie为主，删除redis中，把cookie覆盖redis
         * 3.同步到了redis中以后，覆盖本地cookie购物车数据，保证本地购物车的数据是同步的
         */

        //从Redis中获取购车车
        String shopCartJsonRedis = redisOperator.get(FOODIE_SHOPCART + ":" + userId);
        //从cookie中获取购物车
        String shopCartStrCookie = CookieUtils.getCookieValue(request, FOODIE_SHOPCART, true);
        if (StringUtils.isBlank(shopCartJsonRedis)) {
            //redis为空，cookie不为空
            if (StringUtils.isNotBlank(shopCartStrCookie)) {
                redisOperator.set(FOODIE_SHOPCART + ":" + userId, shopCartStrCookie);
            }
        } else {
            //redis不为空,cookie不为空，合并cookie和redis中购物车的商品数据（如果是同一商品，则覆盖redis）
            if (StringUtils.isNotBlank(shopCartStrCookie)) {

                /**
                 * 1.已经存在的，把cookie中对应的数量，覆盖redis
                 * 2.该项商品标记为待删除，统一放入一个待删除的list
                 * 3.从cookie中清理所有的待删除list
                 * 4.合并redis和cookie中的数据
                 * 5.更新redis和cookie中
                 */
                List<ShopCartBO> shopCartRedisList = JsonUtils.jsonToList(shopCartJsonRedis, ShopCartBO.class);
                List<ShopCartBO> shopCartCookieList = JsonUtils.jsonToList(shopCartStrCookie, ShopCartBO.class);
                //定义一个待删除list
                List<ShopCartBO> pendingDeleteList = new ArrayList<>();
                for (ShopCartBO redisShopCart : shopCartRedisList) {
                    String redisSpecId = redisShopCart.getSpecId();
                    for (ShopCartBO cookieShopCart : shopCartCookieList) {
                        String cookieSpecId = redisShopCart.getSpecId();
                        if (redisSpecId.equals(cookieSpecId)) {
                            //覆盖购买数量，不累加，参考京东
                            redisShopCart.setBuyCounts(cookieShopCart.getBuyCounts());
                            //把cookie的shopcart放入待删除列表，用于最后的删除与合并
                            pendingDeleteList.add(cookieShopCart);
                        }
                    }
                }
                //从现有的cookie中删除对应覆盖过的数据
                shopCartCookieList.removeAll(pendingDeleteList);
                //合并两个list
                shopCartRedisList.addAll(shopCartCookieList);
                //更新到redis和cookie中
                redisOperator.set(FOODIE_SHOPCART + ":" + userId, JsonUtils.objectToJson(shopCartRedisList));
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, JsonUtils.objectToJson(shopCartRedisList), true);
            } else {
                //redis不为空，cookie为空，直接把redis覆盖cookie
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, shopCartJsonRedis, true);
            }
        }

    }

    private Users setNullProperty(Users userResult) {
        userResult.setPassword(null);
        userResult.setMobile(null);
        userResult.setEmail(null);
        userResult.setCreatedTime(null);
        userResult.setUpdatedTime(null);
        userResult.setBirthday(null);
        return userResult;
    }


    /**
     * 用户退出登录的方法
     *
     * @param userId
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "用户退出登陆", notes = "用户退出登陆", httpMethod = "POST")
    @PostMapping("/logout")
    public IMOOCJSONResult logout(@RequestParam String userId,
                                  HttpServletRequest request,
                                  HttpServletResponse response) {
        //清除用户相关信息的cookie
        CookieUtils.deleteCookie(request, response, "user");
        //分布式会话中需要清除用户数据
        redisOperator.del(REDIS_USER_TOKEN + ":" + userId);
        //用户退出登陆，需要清空购物车
        CookieUtils.deleteCookie(request, response, FOODIE_SHOPCART);


        return IMOOCJSONResult.ok();
    }


}
